home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / CRS / crs53.d81 / 28may87s.pma / CXDISK.ASM < prev    next >
Assembly Source File  |  1979-12-31  |  35KB  |  1,778 lines

  1.  
  2.  
  3.  
  4. ;
  5. ;    *****************************************
  6. ;    *                    *
  7. ;    *    Commodore Disk    Controller    *
  8. ;    *    Module for CP/M 3.0 BIOS    *
  9. ;    *                    *
  10. ;    *****************************************
  11. ;
  12. ;
  13. ;
  14.     title 'CXDISK   Commodore C-128 Disk Controller    15 Apr 86'
  15.  
  16.  
  17.  
  18.  
  19. ; CP/M 3 Disk definition macros
  20.  
  21.     maclib    cpm3
  22.  
  23.     maclib    z80
  24.  
  25. ; C-128 system equates
  26.  
  27.     maclib    cxequ
  28.  
  29.     page
  30.  
  31. ; Disk drive dispatching tables for linked BIOS
  32.  
  33.     public    cmdsk0,cmdsk1,cmdsk2,cmdsk3,cmdsk4
  34.  
  35. ; System Control Block variables
  36.     extrn    @ermde        ; BDOS error mode
  37.  
  38. ; Utility routines in standard BIOS
  39.     extrn    ?wboot        ; warm boot vector
  40.     extrn    ?pmsg        ; print message @<HL> up to 00
  41.                 ; saves <BC> & <DE>
  42.     extrn    ?pdec        ; print binary number in <HL> from 0 to 65535
  43.     extrn    ?pderr        ; print BIOS disk error header
  44.     extrn    ?conin,?cono    ; con in and out
  45.     extrn    ?const        ; get console status
  46.     extrn    ?sctrn        ; sector translation routine
  47.     extrn    @covec
  48.  
  49. ;    status line calls
  50.  
  51.     extrn    ?save,?recov,?stat
  52.  
  53. ; System function call
  54.     extrn    ?kyscn
  55.     extrn    ?fun65
  56.     extrn    ?bank
  57.     extrn    ?di$int
  58.  
  59.     public    ?dskst
  60.     public    ?dkmov
  61.     extrn    ?stat,@st40
  62.  
  63.     page
  64. ;
  65. ; Initialization entry point.
  66. ; called for first time initialization.
  67. ;
  68.     DSEG
  69. init$154X:
  70.     xra    a
  71.     sta    fast
  72.     lxi    h,MFM$table
  73.     shld    MFM$tbl$ptr
  74.     ret
  75.  
  76.  
  77.     page
  78. ;
  79. ; This entry is called when a logical drive is about to
  80. ;  be logged into for the purpose of density and type determination.
  81. ;  It may adjust the parameters contained in the disk
  82. ;  parameter header pointed to by <DE>
  83. ;
  84.     DSEG
  85. ;
  86. ;    if disk type GCR or drive type 1541 or 1581(reports as GCR)
  87. ;       if sector size is 256 bytes
  88. ;          if 1st sector has 'CBM' (1st 3 bytes)
  89. ;             if last byte = -1 (0FFh)
  90. ;                set C128 double sided
  91. ;             else
  92. ;                set C128 single sided
  93. ;             endif
  94. ;          else
  95. ;             set C64 type
  96. ;          endif
  97. ;       else  (512 byte sector size)
  98. ;          set C1581 type
  99. ;       endif
  100. ;    else (must be MFM)
  101. ;       TEST MFM
  102. ;    endif
  103. ;
  104. login$154X:
  105.     call    get$drv$info    ; set the drive to check (DPH$pointer set)
  106.  
  107.     mvi    a,vic$test
  108.                 ; ***** add code to reset 1581 drive *****
  109.     call    ?fun65
  110.     mov    b,a
  111.     ani    0ch
  112.     cpi    0ch        ; fast drive ?
  113.     jrz    commodore$type    ; no, must be 1541 type
  114.     mov    a,b        ; yes, is a 1571 or 1581
  115.     rlc            ; MSB=1 if NON-Commodore disk 
  116.     jrc    MFM$type    ; 1571 NON-Commodore disk is MFM type
  117.  
  118.     page
  119. ;
  120. ;    Commodore Type disk is a disk that is in GCR format (1571)
  121. ;    Or Standard Commodore format for 1581 (Has a Commodore dir track)
  122. ;
  123. commodore$type:
  124.     lhld    DPH$pointer
  125.     dcx    h
  126.   if    use$1581
  127.     mov    a,b        ; get the status byte
  128.     ani    30h        ; save only the sector size info
  129.     cpi    20h        ; 512 byte sectors?
  130.     jrnz    set$15x1$type    ; no, set up as 1571 or 1541
  131.                 ; yes, set 1581 type drive
  132. ;
  133. ;
  134. ;
  135. set$1581$type:
  136.     mvi    m,dsk$1581    ; yes, set up as 1581 double sided
  137.     lxi    d,dpb$1581 
  138.     jr    set$dpb$only
  139.  
  140.   endif
  141.  
  142. set$15x1$type:
  143.     mvi    m,dsk$c64
  144.     lxi    d,dpb$c64$cpm    ; set DPB to C64
  145.     call    set$dpb$only
  146.  
  147.     xra    a
  148.     sta    vic$sect    ; set track 1 sector 0 (1st sector
  149.     inr    a        ; on the disk)
  150.     sta    vic$trk
  151.  
  152.     lxi    h,@buffer
  153.     shld    local$DMA    ; move DMA pointer to disk buffer
  154.     call    login$rd
  155.     ana    a        ; read error ?
  156.     rnz            ; yes, just return
  157.  
  158.     RCALL    FR$check$CBM
  159.     rnz            ; return if not 'CBM'
  160.                 ; A=0FFh if double sided
  161.     inr    a
  162.     lhld    DPH$pointer
  163.     dcx    h        ; does not affect flags
  164.     mvi    m,dsk$c128
  165.  
  166.     lxi    d,dpb$c128$SS
  167.     jrnz    set$dpb$only
  168.  
  169.     lxi    d,dpb$c128$DS
  170.  
  171.     page
  172. ;
  173. ;
  174. ;
  175. set$dpb$only:
  176.     lxi    b,0        ; set sector translation to zero
  177. set$format:
  178.     lhld    DPH$pointer
  179.     mov    m,c
  180.     inx    h
  181.     mov    m,b        ; install sector translation
  182.     lxi    b,25-1        ; ofset to DPB
  183.     dad    b        ; HL points to DPB now
  184.     lxi    b,17        ; dpb size
  185.     xchg            ; move to DPB location
  186.     ldir
  187.     ret
  188.  
  189.     page
  190. ;
  191. ;    TEST MFM()
  192. ;    save number bytes/sector
  193. ;       if double sided
  194. ;          mark two sided
  195. ;       endif
  196. ;       find start and end sector numbers
  197. ;       scan table of disk for match (if more then 1 match ask user) 
  198. ;
  199. MFM$type:
  200.     mvi    c,01100000b
  201.     ana    c            ; A = status(trk1) shifted left 1 
  202.     push    psw            ; save in case bad query
  203.     push    b            ; save BC
  204.  
  205.     call    get$max$num$B        ; used to set the pointer only
  206.     mov    b,m            ; get size, and disk lock flag
  207.     inx    h
  208.     mov    a,m
  209.     inx    h
  210.     mov    h,m            ; get last MFM$mactch$ptr
  211.     mov    l,a
  212.     mov    a,b            ; get lock flag in A
  213.     ani    80h            ; lock bit set ?
  214.     sta    lock$flag        ;   (save old lock status)
  215.     shld    last$match        ; save last match pointer
  216.     jrz    not$$locked$entry    ; yes, then set same disk type
  217. ; set$locked$entry
  218.     xra    a
  219.     sta    lock$flag
  220.     mvi    c,0B0h
  221.     lda    vic$data        ; get sector size info
  222.     ana    c
  223.     mov    b,a            ; save disk sector size info
  224.     xchg                ; save HL
  225.     lhld    DPH$pointer
  226.     dcx    h
  227.     mov    a,c
  228.     ana    m            ; get old disk sector size
  229.     cmp    b            ; are they the same?
  230.     jrnz    not$locked$entry    ; no, then unlock disk anyway
  231.  
  232.     xchg                ; get last match pointer (in DE)
  233.     pop    psw            ; yes, remove two data elements 
  234.     pop    psw            ; ..save on stack
  235.     jr    set$this$entry
  236.  
  237. not$locked$entry:
  238.     lxi    h,MFM$match$tbl        ; clear Match table
  239.     shld    MFM$cur$ptr
  240.     lxi    d,MFM$match$tbl+1
  241.     mvi    m,0
  242.     lxi    b,(MFM$tbl$entries*2)-1+1+1    ; table, offset and count
  243.     ldir
  244.     mvi    a,4
  245.     sta    vic$trk            ; do query on track 4
  246.     mvi    a,vic$query
  247.     call    ?fun65
  248.     pop    b            ; recover BC
  249.     ani    0eh            ; query error ?
  250.     jrnz    query$error        ; yes, use only bits 5 and 6 
  251.     lda    @buffer            ; get trk 4 status
  252.     mov    b,a            ; save in B
  253.     ani    0eh            ; trk 4 status error ?
  254.     jrnz    query$error        ; yes, use only bits 5 and 6
  255.     mov    a,b            ; recover B (trk 4 status)
  256.     add    a            ; shift left
  257.     ana    c            ; mask sector size bits
  258.     mov    b,a
  259.     pop    psw            ; get trk 1 sector size bits
  260.     cmp    b            ; same as trk 4 sector size?
  261.     mvi    c,01111111b
  262.     jrz    trk$1$trk$4        ; yes, (then test for mult format)
  263.     mvi    a,80h            ; set MSB to mean mult format
  264.     add    b            ; ..(track 0 different sector size
  265.                     ; ..then track 4) 
  266.     mov    b,a            ; save in B
  267.     mvi    c,11111111b
  268. trk$1$trk$4:
  269.     lda    @buffer+1        ; get number of sectors/track
  270.     sui    4            ; remove 4 to extend the range
  271.     add    a            ; shift    left
  272.     add    b            ; combine with rest of mask
  273.     mov    b,a            ; save in B for now
  274.  
  275.     lda    @buffer+3        ; minimum sector number
  276.     add    b            ; add in start sector #
  277.     push    psw            ; save on stack for a moment
  278.  
  279. query$error:
  280.     pop    psw            ; get value to match 
  281.     ana    c            ; test only those bits in the mask
  282.  
  283.     lhld    MFM$tbl$ptr
  284.     mvi    b,MFM$tbl$entries
  285. check$next:
  286.     push    b            ; save BC for a moment
  287.     mov    b,a            ; move compare value to 
  288.     mov    a,m            ; get type info
  289.     ana    c            ; test only the good info
  290.     cmp    b            ; match the current type byte
  291.     mov    a,b            ;   (recover A)
  292.     pop    b            ;   (recover BC)
  293.     jrnz    not$found        ; no, do not queue data
  294.                     ; yes queue table entry address
  295.  
  296.     xchg                ; save adr in DE
  297.     lhld    MFM$cur$ptr
  298.     mov    m,e
  299.     inx    h
  300.     mov    m,d
  301.     inx    h
  302.     shld    MFM$cur$ptr
  303.     lxi    h,MFM$count
  304.     inr    m            ; add one to counter
  305.     xchg
  306.  
  307.     page
  308. ;
  309. ;
  310. not$found:
  311.     lxi    d,32            ; table entry size
  312.     dad    d
  313.     djnz    check$next
  314.  
  315.     lda    MFM$count        ; number of matches in table 
  316.     ana    a            ; test for zero
  317.     jz    tell$user$no$entry    ; none, tell the user 
  318.  
  319.     dcr    a            ; only one ?
  320.     jrnz    user$select        ; no, go check with user (which one)
  321.     lhld    MFM$match$tbl        ; yes, use the only one found
  322.  
  323. ;
  324. ;    install data from pointer in HL
  325. ;
  326. set$this$entry:
  327.     push    h        ; save table pointer
  328.     inx    h
  329.     mov    a,m        ; get type info. 
  330.     xchg            ; save table address in DE
  331.     lhld    DPH$pointer
  332.     dcx    h
  333.     mov    m,a        ; save type code
  334.     xchg            ; get table adr to HL
  335.     inx    h        ; HL points to sector translation table 
  336.     mov    c,m        ; ..zero if none
  337.     inx    h
  338.     mov    b,m
  339.     inx    h        ; HL points to DPB
  340.     xchg            ; DE points to DPB (HL trash)
  341.     call    set$format
  342.     mov    b,m        ; get the number of sect/trk from MFM table
  343.     lda    lock$flag    ; get the current lock flag value
  344.     ora    b        ; combine with sect/trk
  345.     xchg            ; HL=to adr,  DE=from adr
  346.     mov    m,a        ; install sect/trk and lock flag
  347.     pop    d        ; recover table pointer
  348.     inx    h
  349.     mov    m,e
  350.     inx    h
  351.     mov    m,d        ; save MFM table pointer at end of DPH
  352.     ret
  353.  
  354.     page
  355. ;
  356. ;    let the user select the Disk type (s)he wants
  357. ;
  358. user$select:
  359.     inr    a            ; number of entries to try to match
  360.     mov    b,a            ; set in B as loop count
  361.     lhld    last$match        ; get value to match with
  362.     mov    d,h
  363.     mov    e,l            ; last match pointer is in DE
  364.  
  365.     lxi    h,MFM$match$tbl
  366.     shld    MFM$cur$ptr
  367.     mvi    c,0            ; start offset at zero
  368.  
  369. try$next$format:
  370.     mov    a,e
  371.     cmp    m
  372.     inx    h
  373.     jrnz    not$last$match
  374.     mov    a,d
  375.     cmp    m
  376.     jrnz    not$last$match
  377. ;
  378. ; match, set pointer
  379. ;
  380.     mov    a,c            ; get offset in A
  381.     push    psw
  382.     call    save$dsk$window
  383.     pop    psw
  384.     jr    set$offset
  385.  
  386. not$last$match:
  387.     inx    h            ; each pointer uses two bytes 
  388.     inr    c            ; advance the index
  389.     djnz    try$next$format        ; test for more, loop if so
  390.  
  391.     call    save$dsk$window
  392.  
  393.     lhld    MFM$cur$ptr
  394. user$loop:
  395.     mov    e,m            ; HL=(MFM$cur$ptr)
  396.     inx    h
  397.     mov    d,m
  398.     lxi    h,22            ; offset to NAME field
  399.     dad    d            ; point to Disk name
  400.     call    dsk$window$old
  401.  
  402. dsk$user$sel$wait:
  403.     call    ?kyscn
  404.     inr    b            ; test for key pressed
  405.     jrz    dsk$user$sel$wait
  406.     dcr    b            ; adjust back
  407.     mov    a,b            ; move matrix position to A
  408.     cpi    SF$exit
  409.     jrnz    CK$dsk$user$rt
  410.  
  411.     mov    a,c
  412.     ani    4            ; control key down ?
  413.     jrz    no$cntr$key        ; no, don't lock this selection
  414.     mvi    a,80h            ; yes, lock disk type to this drive
  415. no$cntr$key:
  416.     sta    lock$flag        ;
  417.     call    dsk$window$remove
  418.     lhld    MFM$cur$ptr
  419.     mov    e,m
  420.     inx    h
  421.     mov    d,m
  422.     xchg
  423.     jr    set$this$entry
  424.  
  425.     page
  426. ;
  427. ;
  428. ;
  429. CK$dsk$user$rt:
  430.     cpi    SF$right        ;
  431.     jrnz    CK$dsk$user$lf
  432.  
  433. ; move window down
  434.     lda    MFM$count        ; get number of items in list
  435.     mov    b,a            ; save in B
  436.     lda    MFM$offset        ; get current position
  437.     inr    a            ; advance position
  438.     cmp    b            ; at last position ? (n-1+1 =count)
  439.     jrnz    set$offset        ; no, then use A as new position
  440.     xra    a            ; yes, move back to start
  441.     jr    set$offset
  442.     
  443. CK$dsk$user$lf:
  444.     cpi    SF$left            ;
  445.     jrnz    dsk$user$sel$wait
  446.  
  447. ; move window up
  448.     lda    MFM$offset
  449.     dcr    a            ; back up offset (under flow?)
  450.     jp    set$offset        ; result positive, jump
  451.     lda    MFM$count        ; get last item number
  452.     dcr    a            ; pointer is 0 to n-1 (not 1 to n)
  453. set$offset:
  454.     sta    MFM$offset        ; set new list offset
  455.     inr    a            ; add one to adjust for DCR below
  456.     lxi    h,MFM$match$tbl        ; set to the beginning
  457.  
  458. adjust$dsk$loop:
  459.     shld    MFM$cur$ptr        ; set pointer here !
  460.     dcr    a            ; at offset yet?
  461.     jrz    user$loop        ; yes, go display name
  462.     inx    h
  463.     inx    h
  464.     jr    adjust$dsk$loop
  465.  
  466.     page
  467. ;
  468. ;
  469. ;
  470. tell$user$no$entry:
  471.     lda    vic$data        ; get disk test status
  472.     ani    0b0h            ; save only sector size and MFM flag
  473.     lhld    DPH$pointer
  474.     dcx    h
  475.     mov    m,a            ; set disk size and Type0 (MFM)
  476.  
  477.     lxi    h,dsk$window*256+buff$pos
  478.     lxi    d,no$dsk$msg
  479. disp$msg$DE$HL:
  480.     call    dsk$window$new
  481. dsk$no$entry$wait:
  482.     call    ?kyscn
  483.     inr    b
  484.     jrz    dsk$no$entry$wait
  485.     dcr    b
  486.     mov    a,b
  487.     cpi    SF$exit
  488.     jrnz    dsk$no$entry$wait
  489. ;    jr    dsk$window$remove
  490.  
  491.     page
  492. ;
  493. ;
  494. ;
  495. dsk$window$remove:
  496.     lhld    window$info
  497.     mov    b,h
  498.     mov    c,l
  499.     jmp    ?recov
  500. ;
  501. ;
  502. ;
  503. save$dsk$window:
  504.     lxi    h,dsk$window*256+buff$pos    ; H=size l=pos
  505.     shld    window$info
  506.     mov    b,h
  507.     mov    c,l
  508.     jmp    ?save
  509. ;
  510. ;
  511. ;
  512. dsk$window$new:
  513.     shld    window$info
  514.     xchg
  515.     mov    b,d
  516.     mov    c,e
  517.     push    h
  518.     call    ?save
  519.     pop    h
  520.  
  521. dsk$window$old:
  522.     lda    window$info        ; get start index
  523.     inr    a
  524.     mov    c,a            ; place in C
  525.  
  526. dsk$out$next:
  527.     push    h
  528.     lhld    window$info
  529.     mov    a,h
  530.     add    l            ; compute max index (start+size)
  531.     dcr    a            ; ..less 1
  532.     pop    h
  533.     cmp    c
  534.     rz    
  535.     mov    b,m
  536.     call    dsk$B$out
  537.     inx    h
  538.     jr    dsk$out$next
  539.  
  540. ;
  541. ;
  542. ;
  543. dsk$B$out:
  544.     mvi    a,01000000b            ; set reverse video attr
  545.     push    b
  546.     push    h
  547.     call    ?stat                ; display space
  548.     pop    h
  549.     pop    b                ; recover count
  550.     inr    c
  551.     ret
  552.  
  553.     page
  554. ;
  555. ; disk READ and WRITE entry points.
  556. ; These entries are called with the following arguments:
  557. ;    relative drive number in @rdrv (8 bits)
  558. ;    absolute drive number in @adrv (8 bits)
  559. ;    disk transfer address in @dma (16 bits)
  560. ;    disk transfer bank    in @dbnk (8 bits)
  561. ;    disk track address    in @trk (16 bits)
  562. ;    disk sector address    in @sect (16 bits)
  563. ;    pointer to XDPH in <DE>
  564. ;
  565. ;   return with an error code in <A>
  566. ;     A=0    no errors
  567. ;     A=1    non-recoverable error
  568. ;    A=2    disk write protected
  569. ;    A=FF    media change detected
  570. ;
  571.     DSEG
  572. read$154X:
  573.     call    get$drv$info
  574.     jm    mfm$rd
  575.     call    set$up$GCR        ; compute effective track and sector
  576. login$rd:
  577.     lda    vic$drv
  578.     mov    b,a
  579.     lda    fast            ; get fast flags
  580.     ana    b            ; isolate fast bit for this drive
  581.     jrnz    rd$fast            ; go handle fast drive
  582. rd$slow:
  583.     mvi    a,vicrd            ; read a sector of data (A=1)
  584.     call    dsk$fun            ; a=0 if no errors
  585.     jnz    test$error        ; check for disk error or media change
  586. ;
  587. ;
  588. ;
  589. buf$move:
  590.     xra    a            ; set direction to read
  591.     call    ?dkmov            ; go move buffer to DMA
  592.     lda    sect$cnt
  593.     ana    a
  594.     rz                ; a=0 means not read errors
  595.     call    set$up$next
  596.     jr    rd$slow
  597.  
  598.     page
  599. ;
  600. ;    A=drive type info
  601. ;
  602. mfm$rd:
  603.     call    set$up$MFM
  604.  
  605. rd$fast:
  606.     mvi    a,vic$rd$f
  607.     call    dsk$fun            ; go read the disk
  608.  
  609.     ani    0eh            ; mask off error bits
  610.     jrnz    test$error
  611.  
  612.     call    get$sector$size
  613.     inr    d
  614.     inr    e            ; adjust count for pre-decrement
  615.  
  616.     call    ?di$int
  617.     lxi    b,0DD00h        ; D2PRA
  618.     inp    a            ; get current clock polarity 
  619.     xri    10h            ; toggle clk$bit
  620.     outp    a            ; to have status sent (extra clock
  621.                     ; supplied by rd$1571$data for multi
  622.                     ; sector transfers)
  623.     lda    vic$count
  624. rd$multi$sect:
  625.     push    psw
  626.     push    d            ; save the sector size
  627.     call    rd$1571$data        ; read disk data to DMA address
  628.     pop    d
  629.  
  630.     lda    vic$data
  631.     ani    0eh
  632.     jrnz    test$error$pop        ; A=0 if no errors
  633.     pop    psw
  634.     dcr    a
  635.     jrnz    rd$multi$sect
  636.     ei
  637.     lda    sect$cnt
  638.     ana    a            ; any sectors left to read
  639.     jrz    done$rd$1571
  640.  
  641.     call    set$up$next
  642.     jr    rd$fast
  643.  
  644. done$rd$1571:
  645.     lxi    b,0DD00h        ;   D2PRA
  646.     inp    a
  647.     ani    not(10h)        ; set clk$bit hi
  648.     outp    a
  649.     xra    a            ; A=0 for no errors
  650.     ret
  651.  
  652.  
  653.     page
  654. ;
  655. ;
  656. ;
  657. write$154X:
  658.     call    get$drv$info
  659.     jm    mfm$wr
  660.     call    set$up$GCR
  661.     lda    vic$drv
  662.     mov    b,a
  663.     lda    fast            ; get fast flags
  664.     ana    b            ; isolate fast bit for this drive
  665.     jrnz    wr$fast$drive        ; go handle fast drive
  666. wr$slow:
  667.     mvi    a,-1            ; set direction to write
  668.     call    ?dkmov            ; go move DMA to buffer
  669.  
  670.     mvi    a,vicwr            ; write a sector of data
  671.     call    dsk$fun            ; a=0 if no errors
  672.     ani    0eh
  673.     jrnz    test$error
  674.     lda    sect$cnt
  675.     ana    a
  676.     rz
  677.     call    set$up$next
  678.     jr    wr$slow
  679.  
  680. test$error$pop:
  681.     pop    psw
  682. test$error:
  683.     ei
  684.     lda    vic$data
  685.     ani    0fh            ; check for disk error or media change
  686.     cpi    0bh            ; disk change ?
  687.     jrz    change$error
  688.     cpi    08h            ; test for write protect error
  689.     jrz    write$prot$error
  690.  
  691.     mvi    a,1            ;  get general error flag
  692.     ret
  693.  
  694. ;
  695. ;
  696. write$prot$error:
  697.     mvi    a,2
  698.     ret
  699.  
  700. ;
  701. ;
  702. change$error:
  703.     mvi    a,-1
  704.     ret
  705.  
  706.     page
  707. ;
  708. ;
  709. ;
  710. mfm$wr:
  711.     call    set$up$MFM
  712. wr$fast$drive:
  713.     mvi    a,vic$wr$f
  714.     call    dsk$fun            ; go send the write command
  715.  
  716.     call    get$sector$size        ; setup DMA adr and transfer count
  717.     lda    vic$count
  718. wr$multi$sect:
  719.     push    psw
  720.     push    d            ; save sector size
  721.     call    wr$1571$data        ; write data to disk from DMA address
  722.     pop    d
  723.     ani    0eh
  724.     jrnz    test$error$pop
  725.     pop    psw
  726.     dcr    a
  727.     jrnz    wr$multi$sect
  728.  
  729.     ei
  730.     lda    sect$cnt
  731.     ana    a
  732.     rz                ; return if no errors (A=0)
  733.     call    set$up$next
  734.     jr    wr$fast$drive
  735.  
  736.     page
  737. ;
  738. ;
  739. ;
  740. get$drv$info:
  741.     lhld    @dma
  742.     shld    local$dma
  743.     xchg
  744.     shld    DPH$pointer
  745.  
  746.     lda    @adrv            ; get drive number (0 to F)
  747.     ana    a
  748.     cz    drive$A$E
  749.     cpi    'E'-'A'            ; test if drive E
  750.     cz    drive$A$E
  751.     dcx    h            ; point at drive mask
  752.     dcx    h
  753.     mov    a,m            ; get drive mask
  754.     mov    b,a            ; save in B
  755.     sta    vic$drv            ; save vic drive # (values 1,2,4,8)
  756.  
  757.     inx    h            ; point at disk type
  758.     xra    a
  759.     sta    sect$cnt        ; clear the count
  760.     inr    a
  761.     sta    vic$count
  762.     mov    a,m            ; get disk type
  763.     ana    a
  764.     ret
  765.  
  766. ;
  767. ;    drive A and E share the same physical disk drive (unit 8)
  768. ;
  769. drive$A$E:
  770.     mov    b,a
  771.     lda    curdrv            ; get the current drive def
  772.     cmp    b            ; curdrv = requested drive ?
  773.     rz                ; yes, return
  774.                     ; no, tell the user to swap disk
  775.     push    h
  776.     push    d
  777.     push    b
  778. send$messg:
  779.     mov    a,b            ; get requested drive # to A
  780.     sta    curdrv            ; make this the current drive
  781.     adi    'A'            ; compute drive letter
  782.     sta    msg$drv
  783.  
  784.     RCALL    FR$bell            ; ring BELL to alert user
  785.     lxi    h,swap$msg$lng*256+buff$pos
  786.     lxi    d,swap$msg
  787.     call    disp$msg$DE$HL        ; disp and wait for CR
  788.  
  789.     mvi    a,vic$test
  790.     call    ?fun65
  791. ;    ani    0fh
  792. ;    cpi    0ch            ; not fast ERROR ?
  793. ;    jrz    exit$drv$A$E        ; yes, return that's not a problem
  794. ;    ani    0eh            ; other error type ?
  795. ;    jrnz    send$messg
  796. exit$drv$A$E:
  797.     pop    b
  798.     pop    d
  799.     pop    h
  800.     mov    a,b
  801.     ret
  802.  
  803. swap$msg:    db    'Insert Disk '
  804. msg$drv:    db    'X in Drive A'
  805.  
  806. swap$msg$lng    equ    $-swap$msg+2    ; +2 for leading and trailing spaces
  807.  
  808.     page
  809. ;    
  810. ;
  811. ;
  812. get$max$num$b:
  813.     lhld    DPH$pointer
  814.     lxi    b,42            ; offset to number of sectors on track
  815.     dad    b
  816.     mov    a,m            ; get number sectors/track/side
  817.     ani    1fh
  818.     mov    b,a
  819.     ret
  820. ;
  821. ;
  822. ;
  823. get$sector$size:
  824.     lhld    DPH$pointer
  825.     dcx    h
  826.     mov    a,m            ; disk type in B (bit 5,4 size info)
  827.     rrc                ; ..00 = 080h byte sectors
  828.     rrc                ; ..01 = 100h byte sectors
  829.     rrc                ; ..10 = 200h byte sectors
  830.     rrc                ; ..11 = 400h byte sectors
  831.     ani    3
  832.     jrz    set$128
  833.     jpo    not$3            ; jump if (A=) 01b or 10b
  834.     inr    a            ; make A = 4
  835. not$3:
  836.     mvi    e,0            ; set E to zero
  837.     mov    d,a            ; set sector size (1,2 or 4)
  838. get$DMA:
  839.     lhld    local$DMA        ; get the current DMA pointer
  840.     ret
  841.  
  842. set$128:
  843.     lxi    d,128
  844.     jr    get$DMA 
  845.  
  846.     page
  847. ;
  848. ;
  849. ;
  850.     DSEG
  851. set$up$GCR:
  852.     cpi    dsk$c128
  853.     jnz    tst$next
  854.  
  855.     mvi    a,4
  856.     sta    sect$cnt
  857.     lxi    h,sect$buffer
  858.     shld    sect$buf$ptr
  859.  
  860.     lhld    @trk            ; 1 K sector pointer 
  861.     dad    h
  862.     dad    h            ; make 256 byte pointer
  863. ;
  864. ;    build a list of tracks and sectors
  865. ;
  866. next$sect:
  867.     shld    @trk
  868.     RCALL    FR$trk$sect
  869.     lhld    vic$trk            ; get trk(L) and sector(H) to HL
  870.     xchg
  871.     lhld    sect$buf$ptr
  872.     mov    m,e
  873.     inx    h
  874.     mov    m,d
  875.     inx    h
  876.     shld    sect$buf$ptr
  877.     lhld    @trk
  878.     inr    l            ; update saved above at next$sect
  879.     mov    a,l
  880.     ani    3
  881.     jrnz    next$sect
  882. ;
  883. ;    check list of trk-sectors for number of sectors on this trk
  884.     lxi    h,sect$buffer
  885.     shld    sect$buf$ptr
  886.     lda    vic$drv
  887.     mov    b,a
  888.     lda    fast
  889.     ana    b            ; drive type 1571
  890.     jrz    handle$1541        ; no, handle as 1541
  891.  
  892.     lda    sect$cnt        ; number of sectors to rd/wr
  893.     mov    b,a
  894.     inx    h
  895.     mov    a,m            ; get 1st sector #
  896.     sta    vic$sect
  897.     dcx    h
  898.     mov    a,m            ; get 1st track #
  899.     sta    vic$trk
  900.  
  901. try$next:
  902.     cmp    m            ; test for same trk #
  903.     jrnz    exit$no$match
  904.     inx    h
  905.     inx    h            ; advance to next trk
  906.     shld    sect$buf$ptr
  907.     djnz    try$next    
  908.  
  909. exit$no$match:
  910.     lda    sect$cnt        ; number of sectors to rd/wr
  911.     sub    b            ; remove number left
  912.                     ; (leaving number matched)
  913.     sta    vic$count        ; save number to read
  914.     mov    a,b            ; get remaining count
  915.     sta    sect$cnt        ; save remaining count
  916.     ret
  917.  
  918.  
  919. set$up$next:
  920.     lda    vic$count        ; get number of sectors read
  921.     lhld    local$DMA        ; get current DMA pointer
  922.     add    h            ; advance pointer by number of
  923.     mov    h,a            ; sectors read
  924.     shld    local$DMA
  925. handle$1541:
  926.     lhld    sect$buf$ptr
  927.     mov    a,m
  928.     sta    vic$trk
  929.     inx    h
  930.     mov    a,m
  931.     sta    vic$sect
  932.     inx    h
  933.     shld    sect$buf$ptr
  934.     lda    vic$drv
  935.     mov    b,a
  936.     lda    fast
  937.     ana    b
  938.     jrz    set$up$next$slow
  939.     lda    sect$cnt
  940.     sta    vic$count
  941.     xra    a            ; two reads max with fast drive
  942.     jr    set$up$next$exit
  943.  
  944. set$up$next$slow:
  945.     lda    sect$cnt
  946.     dcr    a
  947. set$up$next$exit:
  948.     sta    sect$cnt
  949.     ret
  950. ;
  951. ;
  952. ;
  953. tst$next:
  954.   if    use$1581
  955.     cpi    dsk$1581
  956.     jrz    c1581$adj
  957.   endif
  958. tst$c64:
  959.     mvi    b,dir$track    ; set the dir track number
  960.     cpi    dsk$c64        ; C64 type disk?
  961.     lda    @sect        ;   get sector # to set
  962.     jrz    set$up$c64    ; yes, go set up for C64 CP/M disk format
  963.                 ; no, set up as no type(direct addressing)
  964. ;
  965. ;    This format is for direct track and sector addressing 
  966. ;
  967. do$type$7:
  968.     mvi    b,255        ; no dir sector
  969. ;
  970. ;    this routine will adjust the track number if necessary.
  971. ;    The C64 CP/M disk has the C64 directory in the center
  972. ;    of the disk. This routine checks and adds one to the track
  973. ;    number if we have reached or passed the directory track. 
  974. ;
  975. set$up$c64:
  976.     sta    VIC$sect    ;
  977.     lda    @trk        ;
  978.     cmp    b        ; carry=1 if A < dir$track
  979.     cmc            ; add one if dir$track or more (carry not set)
  980.     aci    0        ; add the carry bit in
  981.     sta    vic$trk
  982.     ret
  983.  
  984.   if    use$1581
  985. ;
  986. ;******    adjust to read multi-512 byte sectors (system sees 1K sector size)
  987. ;
  988. c1581$adj:
  989.     mvi    a,2        ; 2 512 byte sectors equ 1 1K sector
  990.     sta    vic$count
  991.  
  992.     lda    @trk        ;
  993.     cpi    C1581$dir$trk*2    ; carry=1 if A < dir$track
  994.     cmc            ; add one if dir$track or more (carry not set)
  995.     aci    0        ; add the carry bit in
  996.     rar            ; track=@trk/2 ; carry set if odd
  997.     sta    vic$trk        ;
  998.  
  999.     lda    @sect        ; sector # are 0 to 9 (10 sector/trk)
  1000.     mov    b,a        ;
  1001.     jrnc    bottom$1581    ;
  1002.     adi    80h        ; set top of 1581
  1003. bottom$1581:
  1004.     add    b        ; make 0 to 8
  1005.     inr    a        ; adjust to 1 to 9 (odd numbers only)
  1006.     sta    VIC$sect    ;
  1007.     ret            ;
  1008.  
  1009.   endif
  1010.  
  1011.  
  1012.     page
  1013. ;
  1014. ;    A=dsk$info on entry
  1015. ;
  1016. set$up$MFM:
  1017.     mvi    d,0        ; D=side # (0)
  1018.     mov    e,a        ; save dsk$info in E
  1019.     ani    TypeX        ; look at Type0 to Type7
  1020.     jrz    do$type$0    ;
  1021.     cpi    Type2
  1022.     lda    @trk        ; used by Type1, Type2 and Type3
  1023.     jrz    do$type$2
  1024.     jrc    do$type$1
  1025.  
  1026. ;    cpi    Type6
  1027. ;    jrz    do$type$6
  1028. ;    jnc    do$type$7    ; MSB of sector(byte) set for 2nd side of disk
  1029.  
  1030.     cpi    Type7
  1031.     jz    do$type$7    ; MSB of sector(byte) set for 2nd side of disk
  1032. ;
  1033. ;    only types 0 to 2 and 7 are currenty defined
  1034. ;        Type3 to Type6 will do Type2
  1035. ;do$type$3:
  1036. ;do$type$6:
  1037.  
  1038. do$type$2:
  1039.     mov    b,a        ; save a copy in B
  1040.     sui    40
  1041.     jrc    do$type$0    ; jump if still on side 0
  1042.     mvi    a,79        ; on back side count 39,38,37,...,0
  1043.     sub    b
  1044. set$trk:
  1045.     mvi    d,80h        ; D=side # (1)
  1046.     sta    @trk
  1047.     jr    do$type$0
  1048.  
  1049.     page
  1050. ;
  1051. ;    divide the track number by two and if Head=1
  1052. ;        add #sect/side to @sect
  1053. ;
  1054. do$type$1:
  1055.     cmc            ; carry was set clear it
  1056.     rar            ; divide track by 2 (carry gets LSB)
  1057.     sta    @trk
  1058.     jrnc    do$type$0
  1059.     call    get$max$num$b    ; HL and C changed
  1060.     lda    @sect
  1061.     add    b
  1062.     sta    @sect
  1063.  
  1064. do$type$0:
  1065.     lda    @trk
  1066.     sta    vic$trk
  1067.     call    get$max$num$b    ; B=number of sectors per track per side
  1068.     lda    @sect        ; ..HL and C changed
  1069.     cmp    b
  1070.     jrc    is$side$0
  1071.     mvi    d,80h        ; D=side # (1)
  1072.     bit    C1$bit,e    ; dsk$info in E
  1073.                 ; sector numbering continues on side 1 ?
  1074.     jrnz    is$side$0    ; yes, do not remove side one bias
  1075.     sub    b        ; no, remove side one bias
  1076. is$side$0:
  1077.     mov    c,a        ; hold @sect in C    
  1078.     mov    a,e        ; get dsk$info to A
  1079.     ani    S1        ; A=Starting  sector number (0 or 1)
  1080.     add    c        ; add back @sect
  1081.     ora    d        ; add in the side bit
  1082.     sta    vic$sect
  1083.     ret
  1084.  
  1085.     page
  1086. ;
  1087. ;    input:
  1088. ;        DE = number bytes to read
  1089. ;        HL = DMA address
  1090. ;
  1091.     CSEG
  1092. rd$1571$data:
  1093.     lda    @dbnk            ; get the disk DMA bank
  1094.     call    ?bank            ; set it
  1095.  
  1096.     lxi    b,0DC0Dh        ; D1ICR
  1097. rd$1571$stat$wait:
  1098.     inp    a
  1099.     ani    8            ; data ready bit set?
  1100.     jrz    rd$1571$stat$wait    ; no, loop
  1101.  
  1102.     mvi    c,0ch            ; D1SDR
  1103.     inp    a            ; read the status byte
  1104.     sta    vic$data        ; save it
  1105.     ani    0eh            ; any errors ?
  1106.     jrnz    rd$1571$exit        ; yes, exit
  1107.  
  1108.     lxi    b,0DD00h
  1109.     inp    a            ; get current clock polarity
  1110.  
  1111. rd$1571$next:
  1112.     lxi    b,0DD00h        ; D2PRA
  1113.     xri    10h            ; toggle clk$bit
  1114.     outp    a            ; clock the 1571 for a byte
  1115.  
  1116.     dcr    e            ; DE=count
  1117.     jnz    rd$1571$more        ; leave as normal jump to keep
  1118.     dcr    d            ; the transfer speed at it's max
  1119.     jrz    rd$1571$exit        ; ...
  1120.  
  1121. ;
  1122. rd$1571$more:
  1123.     dcr    b
  1124. rd$1571$wait:
  1125.     mvi    c,0dh            ; D1ICR (DC0Dh)
  1126.     inp    c
  1127.     bit    3,c
  1128.     jz    rd$1571$wait
  1129.     mvi    c,0ch            ; D1SDR
  1130.     ini                ; (hl) <- (bc) ; hl <- hl+1 ; b <- b-1
  1131.     jmp    rd$1571$next
  1132.  
  1133.  
  1134. rd$1571$exit:
  1135.     sta    bank$0            ; restore current mem config
  1136.     ret
  1137.  
  1138.     page
  1139.  
  1140. clk$in    equ    40h
  1141. ;
  1142. ;    input:
  1143. ;        DE = number of bytes to write
  1144. ;        HL = DMA address
  1145. ;
  1146. wr$1571$data:
  1147.     call    ?di$int
  1148. ; do spout inline
  1149.     lxi    b,mode$reg
  1150.     mvi    a,fast$wr$en
  1151.     sta    io$0
  1152.     outp    a            ; set data direction to output
  1153.     sta    bank$0
  1154.  
  1155.     lxi    b,0dc05h        ; low (D1T1h)
  1156.     xra    a
  1157.     outp    a
  1158.     dcr    c            ; low(D1T1l)
  1159.     mvi    a,3            ; clk = osc/3
  1160.     outp    a            ;
  1161.  
  1162.     mvi    c,0eh            ; D1CRA
  1163.     inp    a
  1164.     ani    80h
  1165.     ori    55h
  1166.     outp    a
  1167.     dcr    c            ; D1ICR
  1168.     inp    a
  1169.  
  1170.     lda    @dbnk            ; get the disk DMA bank
  1171.     call    ?bank            ; set it
  1172.  
  1173.     mvi    a,clk$in
  1174.     sta    cur$clk
  1175.  
  1176.     page
  1177. ;
  1178. ;
  1179. clk$wait:
  1180.     lxi    b,0dd00h        ; D2PRA
  1181.     inp    a
  1182.     inp    c            ; debounce
  1183.     cmp    c
  1184.     jrnz    clk$wait
  1185.  
  1186.     lda    cur$clk            ; get old clk value
  1187.     xra    c            ; check if changed 
  1188.     ani    clk$in            ; (only clock in bit)
  1189.     jrz    clk$wait        ; loop if not
  1190.  
  1191.     mov    a,c            ; 
  1192.     sta    cur$clk            ; make this the current clk value
  1193.     lxi    b,0dc0ch        ; D1SDR
  1194.     mov    a,m
  1195.     outp    a            ; send character to drive
  1196.     inx    h            ; advance pointer
  1197.     dcx    d            ; dec the char count
  1198.  
  1199.     inr    c            ; D1ICR
  1200. send$wait:
  1201.     inp    a
  1202.     ani    8
  1203.     jz    send$wait
  1204.  
  1205.     mov    a,d
  1206.     ora    e
  1207.     jnz    clk$wait        ; go send the next byte
  1208.  
  1209. ; do spin
  1210.     lxi    b,0DC0Eh        ; D1CRA
  1211.     inp    a
  1212.     ani    80h
  1213.     ori    8
  1214.     outp    a
  1215.     lxi    b,mode$reg
  1216.     mvi    a,fast$rd$en
  1217.     sta    io$0            ; enable the MMU
  1218.     outp    a            ; set data direction to input
  1219.     sta    bank$0            ; disable MMU
  1220. ; spin done
  1221.  
  1222.     page
  1223.  
  1224.     lxi    b,0DC0Dh        ; D1ICR
  1225.     inp    a            ; clear data pending flag
  1226.  
  1227.     lxi    b,0DD00h        ; D2PRA
  1228.     inp    a
  1229.     ori    10h            ; set clk$bit low (hardware inverted)
  1230.     outp    a            ; 
  1231.  
  1232.     lxi    b,0DC0Dh        ; D1ICR
  1233. wait$status:
  1234.     inp    a
  1235.     ani    8
  1236.     jrz    wait$status
  1237.  
  1238.     lxi    b,0DC0Ch        ; D1SDR
  1239.     inp    d
  1240.  
  1241.     lxi    b,0DD00h        ; D2PRA
  1242.     inp    a
  1243.     ani    not(10h)        ; set clk$bit hi (hardware inverted)
  1244.     outp    a            ; 
  1245.  
  1246.     mov    a,d            ; recover the status byte
  1247.     sta    vic$data
  1248.  
  1249.     ei
  1250.     ret
  1251.  
  1252.     page
  1253. ;
  1254. ;    This routine is used to move a sector of data
  1255. ;     to/from the sector buffer and the DMA pointer.
  1256. ;         A=0 for buffer to DMA  (disk read)
  1257. ;         A<>0 for DMA to buffer (disk write)
  1258. ;
  1259.     CSEG
  1260. ?dkmov:
  1261.     lhld    local$DMA    ; current DMA adr
  1262.     lxi    d,@buffer    ; location of disk read/write buffer
  1263.     lxi    b,256        ; sector size
  1264. ;
  1265. ;
  1266. dk$cont:
  1267.     ora    a
  1268.     jrnz    dsk$read    ; swap pointer for read
  1269.     xchg
  1270. ;
  1271. ;
  1272. dsk$read:
  1273.     lda    @dbnk        ; get the disk bank
  1274.     call    ?bank
  1275.     ldir            ; do the data move
  1276.     sta    bank$0        ; current bank will ALWAYS be 0
  1277.     ret
  1278.  
  1279. ;
  1280. ;
  1281. ;
  1282.     DSEG
  1283. dsk$fun:
  1284.     sta    vic$cmd
  1285.     lda    stat$enable
  1286.     ani    1            ; display of disk info enabled?
  1287.     cnz    disp$dsk$info        ; yes, go display disk info
  1288.     jmp    ?fun65+3        ; go do the function
  1289.  
  1290.     page
  1291. ;
  1292. ;
  1293. ;
  1294.     DSEG
  1295. ?dskst:
  1296. disp$dsk$info:
  1297.     mvi    a,72            ; r/w in col 72 (col 0-79)
  1298.     sta    offset
  1299.     lda    vic$cmd
  1300.     mvi    b,'R'
  1301.     dcr    a            ; ?1 normal$rd
  1302.     jrz    out$cmd$rd
  1303.     dcr    a            ; ?2 normal$wr
  1304.     jrz    out$cmd$wr
  1305.     dcr    a            ; ?3 fast$rd
  1306.     jrz    out$cmd$rd
  1307.     dcr    a            ; ?4 fast$wr
  1308.     rnz
  1309. out$cmd$wr:
  1310.     mvi    b,'W'
  1311. out$cmd$rd:
  1312.     call    disp$B
  1313.     call    disp$space
  1314.     mvi    b,'A'-1
  1315.     lda    vic$drv
  1316. next$drv:
  1317.     inr    b
  1318.     rrc
  1319.     jrnc    next$drv
  1320.  
  1321.     call    disp$B
  1322.     lda    vic$trk
  1323.     call    disp$dec
  1324.     lda    vic$sect
  1325.     ani    80h
  1326.     cz    disp$space
  1327.     mvi    b,'-'
  1328.     cnz    disp$B
  1329.     lda    vic$sect    
  1330.     ani    7fh
  1331.  
  1332.     page
  1333. ;
  1334. ;
  1335. ;
  1336. disp$dec:
  1337.     mvi    b,'0'-1
  1338.  
  1339. conv$loop:
  1340.     inr    b
  1341.     sui    10
  1342.     jrnc    conv$loop
  1343.  
  1344.     adi    '0'+10
  1345.     push    psw
  1346.     call    disp$B
  1347.     pop    psw
  1348. disp$A:
  1349.     mov    b,a
  1350. disp$B:
  1351.     lxi    h,@st40-72+40-8
  1352.     lda    offset
  1353.     mov    e,a
  1354.     mvi    d,0
  1355.     dad    d            ; add the offset
  1356.     mov    m,b            ; save on 40 col display
  1357.  
  1358.     mov    a,e
  1359.     mov    c,a            ; col # in C
  1360.     inr    a
  1361.     sta    offset            ; advance cursor position
  1362.     xra    a            ; no attribute to write
  1363.     call    ?stat
  1364.  
  1365.     lxi    h,@st40
  1366.     lxi    d,vic$screen+40*24    ; update 40 column screen
  1367.     lxi    b,40
  1368.     ldir
  1369.     xra    a
  1370.     ret
  1371.  
  1372. disp$space:
  1373.     mvi    b,' '
  1374.     jr    disp$B
  1375.  
  1376.     page
  1377. ;
  1378. ; Extended Disk Parameter Headers (XDPHs)
  1379. ;
  1380.     CSEG            ; place tables in common
  1381. ;
  1382. ;    1st disk drive on the system
  1383. ;
  1384.     dw    write$154X
  1385.     dw    read$154X
  1386.     dw    login$154X
  1387.     dw    init$154X
  1388.     db    1        ; bit 0 set (drive 0)
  1389.     db    dsk$c128    ; format type byte
  1390. cmdsk0:    
  1391.     dph    0,dpb$0
  1392.  
  1393. dpb$0:
  1394.     dpb    1024,5,159,2048,128,0
  1395.     db    0        ; max sector number and lock flag
  1396.     dw    0        ; MFM table pointer
  1397.  
  1398.     page
  1399. ;
  1400. ;    2nd disk Drive on the system
  1401. ;
  1402.     dw    write$154X
  1403.     dw    read$154X
  1404.     dw    login$154X
  1405.     dw    init$154X
  1406.     db    2        ; bit 1 set (drive 1)
  1407.     db    dsk$c128    ; format type byte 
  1408. cmdsk1:
  1409.     dph    0,dpb$1
  1410.  
  1411. dpb$1:
  1412.     dpb    1024,5,159,2048,128,0
  1413.     db    0        ; max sector number and lock flag
  1414.     dw    0        ; MFM table pointer
  1415.  
  1416.     page
  1417. ;
  1418. ;    3rd disk drive on the system
  1419. ;
  1420.     dw    write$154X
  1421.     dw    read$154X
  1422.     dw    login$154X
  1423.     dw    init$154X
  1424.     db    4        ; bit 2 set (drive 2)
  1425.     db    dsk$c128    ; format type byte
  1426. cmdsk2:    
  1427.     dph    0,dpb$2
  1428.  
  1429. dpb$2:
  1430.     dpb    1024,5,159,2048,128,0
  1431.     db    0        ; max sector number and lock flag
  1432.     dw    0        ; MFM table pointer
  1433.  
  1434.     page
  1435. ;
  1436. ;    4th disk drive on the system
  1437. ;
  1438.     dw    write$154X
  1439.     dw    read$154X
  1440.     dw    login$154X
  1441.     dw    init$154X
  1442.     db    8        ; bit 3 set (drive 3)
  1443.     db    dsk$c128    ; format type byte 
  1444. cmdsk3:
  1445.     dph    0,dpb$3
  1446.  
  1447. dpb$3:
  1448.     dpb    1024,5,159,2048,128,0
  1449.     db    0        ; max sector number and lock flag
  1450.     dw    0        ; MFM table pointer
  1451.  
  1452.     page
  1453. ;
  1454. ;    Drive E: shared with 1st drive (A:)
  1455. ;
  1456.     dw    write$154X
  1457.     dw    read$154X
  1458.     dw    login$154X
  1459.     dw    init$154X
  1460.     db    1        ; bit 0 set (drive 0)
  1461.     db    dsk$c128    ; format type byte 
  1462. cmdsk4:
  1463.     dph    0,dpb$4
  1464.  
  1465. dpb$4:
  1466.     dpb    1024,5,159,2048,128,0
  1467.     db    0        ; max sector number and lock flag
  1468.     dw    0        ; MFM table pointer
  1469.  
  1470.     page
  1471. ;
  1472. ;    NOTE: The blocking factor for all of these formats is
  1473. ;        1K (2K for double sided), thus the fractional
  1474. ;        parts are unusable by CP/M.  They can be accessed
  1475. ;        by absolute sector addressing.
  1476. ;
  1477. ;    NOTE: 1571 and 1541 disk drives use track numbers
  1478. ;        of 1 to 35 and sector numbers of 0 to nn
  1479.  
  1480. ;
  1481. ;        The method used to access the full disk
  1482. ;        is to tell the system that there is 1 sector
  1483. ;        per track and then to use the track # as an
  1484. ;        absolute sector address and do conversion in BIOS.
  1485. ;
  1486. ; DPB FOR C128 CP/M 3.0 disk        ( 170K, 34K larger then C64 CP/M)
  1487. ;    256 byte sectors        ( 170.75K )
  1488. ;    1 sectors/track
  1489. ;        up to 21 physical sectors (0 to 16,17,18 or 20)
  1490. ;    680 tracks/disk (usable, 683 real)
  1491. ;        35 physical tracks (0 to 34)
  1492. ;    1K allocation blocks
  1493. ;    64 directory entries
  1494. ;    track offset of 0
  1495. ;
  1496.     DSEG        ; these tables are moved to common when used
  1497. dpb$c128$SS:        ; (170 allocation units)
  1498.     dpb    1024,1,170,1024,64,0
  1499.  
  1500.     page
  1501. ;
  1502. ; DPB FOR C128 CP/M 3.0 double sided disk    ( 340K )
  1503. ;    1024 byte sectors (phy=256)        ( 341.5K )    
  1504. ;    1 sectors/track
  1505. ;        up to 21 physical sectors (0 to 16,17,18 or 20)
  1506. ;    340 tracks/disk (usable, 1366 real)
  1507. ;        70 physical tracks (0 to 34 side 0, 35 to 69 side 1)
  1508. ;    2K allocation units
  1509. ;    128 directory entrys
  1510. ;    track offset of 0
  1511. ;
  1512. dpb$c128$DS:        ; (170 allocation units)
  1513.     dpb    1024,1,340,2048,128,0
  1514.  
  1515.     page
  1516. ;
  1517. ; DPB FOR C64 CP/M 2.2 disk --             ( 136K )
  1518. ;    256 byte sectors
  1519. ;    17 sectors / tracks    (sector numbering 0-16)
  1520. ;        sector 18 to n on the outer tracks are unused
  1521. ;    34 tracks / disk
  1522. ;        tracks track 2 to 16    (track numbering 0-34)
  1523. ;        track 17 is the C128 directory track (not counted)
  1524. ;        track 19 to 34
  1525. ;    1K allocation blocks
  1526. ;    64 directory entrys
  1527. ;    track offset of 3 (1st two tracks used for CP/M 2.2 boot) plus
  1528. ;    one sector to adjust for sector numbering of 1 to 35 (not 0 to 34)
  1529. ;
  1530. dpb$c64$cpm:        ; (144 allocation units)
  1531.     dpb    256,17,34,1024,64,3
  1532.                 
  1533.     page
  1534. ;
  1535. ; DPB FOR C128 CP/M 3.0 C1581 DSDD (3.5")    (    K )
  1536. ;    512 byte sectors            ( 720K )
  1537. ;    10 sectors/track
  1538. ;    159 tracks/disk
  1539. ;        160 physical tracks 80 on top, 79 on bottom, 1 used for
  1540. ;        BAM and disk directory (1581 DOS) (10 sectors per track)
  1541. ;    2K allocation units
  1542. ;    128 directory entrys (2 allocation units)
  1543. ;
  1544.   if    use$1581
  1545. dpb$1581:        ; (xxx allocation units)
  1546.     dpb    1024,5,159,2048,128,0
  1547.   endif
  1548.  
  1549.     page
  1550. ;
  1551.     DSEG
  1552. MFM$table:
  1553.     db    S256*2+(16*2-8)+1    ; 256 byte sect, 16 sect/trk
  1554.     db    MFM+S256+Type0+C0+S1    ;     DSDD
  1555.     dw    0            ; start on track 2 sect 1 (2 alc)
  1556.     dpb    256,32,40,2048,128,2    ; sect# 1 to 16
  1557.     db    16            ; (top and bottom numbered the same)
  1558.     db    'Epson QX10'        ;1 Epson QX10
  1559.                     ; 160 allocation units
  1560.  
  1561.  
  1562.  
  1563.  
  1564.     db    80h+S512*2+(10*2-8)+1    ; 512 byte sect, 10 sect/trk
  1565. ;    db    S256*2            ; track 0 is 256 bytes/sector
  1566.     db    MFM+S512+Type0+C0+S1    ;    DSDD
  1567.     dw    0            ; start on track 2 sect 1 (2 alc)
  1568.     dpb    512,20,40,2048,128,2    ; sect# 1 to 10
  1569.     db    10            ; (top and bottom numbered the same)
  1570.     db    'Epson QX10'        ;2
  1571.                     ; 200 allocation units
  1572.  
  1573.     page
  1574.  
  1575.     db    S512*2+(8*2-8)+1    ; 512 byte sect 8 sect/trk
  1576.     db    MFM+S512+Type2+C0+S1    ;     SSDD
  1577.     dw    0            ; start on track 1 sector 1 (2 alc)
  1578.     dpb    512,8,40,1024,64,1    ; sect# 1 to 8
  1579.     db    8            ;
  1580.     db    ' IBM-8 SS '        ;3
  1581.                     ; 160 allocation units
  1582.  
  1583.  
  1584.  
  1585.  
  1586.     db    S512*2+(8*2-8)+1    ; 512 byte sect 8 sect/trk
  1587.     db    MFM+S512+Type2+C0+S1    ;     DSDD
  1588.     dw    0            ; start on track 1 sector 1 (1 alc)
  1589.     dpb    512,8,80,2048,64,1    ; sect# 1 to 8
  1590.     db    8            ; (top and bottom numbered the same)
  1591.     db    ' IBM-8 DS '        ;4
  1592.                     ; 160 allocation units
  1593.  
  1594.     page
  1595.  
  1596.     db    S512*2+(10*2-8)+0    ; 512 byte sector, 10 sect/trk
  1597.     db    MFM+S512+Type1+C1+S0    ;    DSDD
  1598.     dw    0            ; start on track 0 sector 10 (2 alc)
  1599.     dpb    512,10,80,2048,128,1    ; sect# 0 to 9 on top (even tracks)
  1600.     db    10            ; sect# 10 to 19 on bottom (odd tracks)
  1601.     db    'KayPro IV '        ;5
  1602.                     ; 200 allocation units
  1603.  
  1604.  
  1605.  
  1606.  
  1607.     db    S512*2+(10*2-8)+0    ; 512 byte sect, 10 sect/trk
  1608.     db    MFM+S512+Type0+C1+S0    ;     SSDD
  1609.     dw    0            ; start on track 1 sector 0 (4 alc)
  1610.     dpb    512,10,40,1024,64,1    ; sect# 0 to 9 
  1611.     db    10            ;
  1612.     db    'KayPro II '        ;6
  1613.                     ; 200 allocation units
  1614.  
  1615.     page
  1616.  
  1617.     db    S1024*2+(5*2-8)+1    ; 1024 byte sect, 5 sect/trk
  1618.     db    MFM+S1024+Type0+C0+S1    ;     SSDD
  1619.     dw    0            ; start on track 3 sector 1 (2 alc)
  1620.     dpb    1024,5,40,1024,64,3    ; sect# 1 to 5
  1621.     db    5            ;
  1622.     db    'Osborne DD'        ;7
  1623.                     ; 200 allocation units
  1624.  
  1625.  
  1626.     db    S512*2+(9*2-8)+1    ; 512 byte sect 9 sect/track (uses 8)
  1627.     db    MFM+S512+Type1+C0+S1    ;     DSDD
  1628.     dw    0            ; start on trk 0, sect 1, hd 1 (1 alc)
  1629.     dpb    512,8,80,2048,64,1    ; sect# 1 to 9
  1630.     db    8            ; (top and bottom numbered the same)
  1631.     db    '  Slicer  '        ;8
  1632.                     ; 160 allocation units
  1633.  
  1634.     page
  1635.  
  1636.     db    S256*2+(16*2-8)+1    ; 256 byte sect, 16 sect/trk
  1637.     db    MFM+S256+Type0+C0+S1    ;     DSDD
  1638.     dw    0            ; start on track 4 sect 1 (2 alc)
  1639.     dpb    256,32,40,2048,128,4    ; sect# 1 to 16
  1640.     db    16            ; (top and bottom numbered the same)
  1641.     db    'Epson Euro'        ;9 Epson European (MFCP/M ?)
  1642.                     ; 160 allocation units
  1643.  
  1644.  
  1645.  
  1646.     db    -1
  1647.     db    MFM            ; 
  1648.     dw    0            ; 
  1649.     dpb    512,20,40,2048,128,2    ; 
  1650.     db    8            ;
  1651.     db    '   None   '        ;10
  1652.  
  1653.     page
  1654.  
  1655.     db    -1
  1656.     db    MFM            ; 
  1657.     dw    0            ; 
  1658.     dpb    512,20,40,2048,128,2    ; 
  1659.     db    8            ;
  1660.     db    '   None   '        ;11
  1661.  
  1662.     db    -1
  1663.     db    MFM            ; 
  1664.     dw    0            ; 
  1665.     dpb    512,20,40,2048,128,2    ; 
  1666.     db    8            ;
  1667.     db    '   None   '        ;12
  1668.  
  1669.     page
  1670.  
  1671.     db    -1
  1672.     db    MFM            ; 
  1673.     dw    0            ; 
  1674.     dpb    512,20,40,2048,128,2    ; 
  1675.     db    8            ;
  1676.     db    '   None   '        ;13
  1677.  
  1678.     db    -1
  1679.     db    MFM            ; 
  1680.     dw    0            ; 
  1681.     dpb    512,20,40,2048,128,2    ; 
  1682.     db    8            ;
  1683.     db    '   None   '        ;14
  1684.  
  1685.     page
  1686.  
  1687.     db    -1
  1688.     db    MFM            ; 
  1689.     dw    0            ; 
  1690.     dpb    512,20,40,2048,128,2    ; 
  1691.     db    8            ;
  1692.     db    '   None   '        ;15
  1693.  
  1694.     db    -1
  1695.     db    MFM            ; 
  1696.     dw    0            ; 
  1697.     dpb    512,20,40,2048,128,2    ; 
  1698.     db    8            ;
  1699.     db    '   None   '        ;16
  1700.  
  1701.  
  1702.     page
  1703. ;
  1704. ;    not functional yet
  1705. ;
  1706.  
  1707. ;    db    S1024*2+(5*2-8)+1    ; 1024 byte sect 5 sect/track
  1708. ;    db    MFM+S1024+Type0+C0+S1    ;     SSDD
  1709. ;    dw    0            ; start on trk 2, sect 1 (2 alc)
  1710. ;    dpb    1024,5,40,2048,128,2    ; sect# 1 to 5
  1711. ;    db    5            ;
  1712. ;    db    'Morrow MD2'        ; 
  1713.  
  1714.  
  1715.  
  1716.  
  1717.  
  1718. ;    db    S1024*2+(5*2-8)+1    ; 1024 byte sect  5 sect/trk
  1719. ;    db    MFM+S1024+Type0+C0+S1    ;     DSDD
  1720. ;    dw    0            ; start on trk 1, sect 1, hd 0 (3 alc)
  1721. ;    dpb    1024,10,40,2048,192,1    ; sect# 1 to 5
  1722. ;    db    5            ;
  1723. ;    db    'Morrow MD3'        ; 
  1724.  
  1725.  
  1726. MFM$tbl$entries    equ    ($-MFM$table)/32
  1727.  
  1728.     db    -1            ; mark end of table
  1729.     db    -1
  1730.  
  1731.     page
  1732.  
  1733.     cseg
  1734. cur$clk:    ds    1
  1735.  
  1736.     dseg
  1737. lock$flag    ds    1
  1738. last$match    ds    2
  1739. window$info:    ds    2
  1740.  
  1741. dsk$window    equ    12
  1742.  
  1743. no$dsk$msg:
  1744.         ;1234567890
  1745.     db    ' Missing  ' 
  1746.  
  1747.  
  1748. MFM$match$tbl:
  1749.     ds    2*MFM$tbl$entries    ; MFM$count MUST follow this parm
  1750. MFM$count:
  1751.     ds    1            ; MFM$offset MUST follow this parm
  1752. MFM$offset:
  1753.     ds    1
  1754.  
  1755. MFM$cur$ptr:
  1756.     ds    2
  1757.  
  1758. DPH$pointer:
  1759.     ds    2
  1760.  
  1761. sect$cnt:
  1762.     ds    1
  1763. sect$buf$ptr:
  1764.     ds    2
  1765. sect$buffer:
  1766.     ds    4*2
  1767.  
  1768. local$DMA:
  1769.     ds    2
  1770.  
  1771. status$atr    equ    0
  1772. offset:        db    0
  1773.  
  1774.     end
  1775.  
  1776.